package com.boby.lib_common.network

import android.util.Log
import com.boby.lib_common.extens.runOnMainThread
import com.boby.lib_common.util.BLog
import com.boby.lib_common.util.JsonUtil

import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.concurrent.Executors

object NetRequest {
    val executorService = Executors.newFixedThreadPool(3)
    val NET_ERROR_CODE = -3
    private val TAG = "NetRequest"

     inline fun <reified T> get(urlString: String,reqHeaders:Map<String,*>? = null, req:Map<String,*>? = null,callback: Net.CallBack<T>?): T? {
         try {

             var reqUrl = urlString
             if(req != null && req.isNotEmpty()){
                 val queryString = req.map { (key, value) -> "$key=${value}" }.joinToString("&")
                 reqUrl += "?$queryString"
             }
//             BLog.d("get","urlString: $reqUrl")
             val url = URL(reqUrl)
             val connection = url.openConnection() as HttpURLConnection
             connection.requestMethod = "GET"
             connection.doOutput = false// 禁止 URL 连接进行输出，默认为“false”
             connection.doInput = true// 使用 URL 连接进行输入，默认为“true”
             connection.useCaches = false
             connection.connectTimeout = 20000
             connection.readTimeout = 20000
             reqHeaders?.map {
                 connection.setRequestProperty(it.key, it.value.toString())
             }
             val responseCode = connection.responseCode
             if (responseCode == HttpURLConnection.HTTP_OK) {
                 val inputStream = connection.inputStream
                 val response = inputStream.bufferedReader(StandardCharsets.UTF_8).use { it.readText() }
                 BLog.d("get","responseCode: $responseCode, response: $response")
                 if(response.isBlank()){
                     callback?.onError(NET_ERROR_CODE,"result isEmpty")
                     return null
                 }else{
                     try {
                         val result = JsonUtil.fromJson<T>(response)
                         callback?.onSuccess(result)
                         return result
                     }catch (e:Exception){
                         callback?.onError(NET_ERROR_CODE,"json convert error")
                         return null
                     }

                 }

             } else {
                 callback?.onError(responseCode,"GET request failed ")
                 return null
             }
         }catch (e:Exception){
             callback?.onError(NET_ERROR_CODE,"GET request failed ${e.message}")
             return null
         }
    }

    inline fun <reified T> post(urlString: String,reqHeaders:Map<String,*>? = null, req: Any? = null, callback: Net.CallBack<T>?): T? {
        try {
            BLog.d("post","url:$urlString")
            val url = URL(urlString)
            val connection = url.openConnection() as HttpURLConnection
            connection.requestMethod = "POST"
            connection.doOutput = true
            connection.doInput = true
            connection.useCaches = false
            connection.connectTimeout = 20000
            connection.readTimeout = 20000

            // 设置请求头，如果需要的话
//        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
//            connection.setRequestProperty("Content-Type", "application/json;charset=utf-8")//设置参数类型是json格式
            reqHeaders?.map {
                connection.setRequestProperty(it.key, it.value.toString())
            }
            if(req != null){
                // 写入POST数据
                val outputStream = connection.outputStream
                if(req is String){
                    BLog.d("post","req:$req")
                    outputStream.write(req.toByteArray(StandardCharsets.UTF_8))
                }else{
                    outputStream.write(JsonUtil.toJson(req).toByteArray(StandardCharsets.UTF_8))
                }

                outputStream.flush()
                outputStream.close()
            }


            val responseCode = connection.responseCode
            if (responseCode == HttpURLConnection.HTTP_OK) {
                val inputStream = connection.inputStream
                val response = inputStream.bufferedReader(StandardCharsets.UTF_8).use { it.readText() }
                BLog.d("post","responseCode: $responseCode, response: $response")

                if(response.isBlank()){
                    callback?.onError(NET_ERROR_CODE,"result isEmpty")
                    return null
                }else{
                    try {
                        BLog.d("sendPostRequest"," $response" )
                        val result = JsonUtil.fromJson<T>(response)
//                    Log.d("sendPostRequest","result: $result" )
                        callback?.onSuccess(result)
                        return result
                    }catch (e:Exception){
                        e.printStackTrace()
                        callback?.onError(NET_ERROR_CODE,"json convert error")
                        return null
                    }

                }
            } else {
                val errorMsg = connection.errorStream.bufferedReader(StandardCharsets.UTF_8).use { it.readText() }
                BLog.d("sendPostRequest"," POST request failed ${errorMsg}" )
                callback?.onError(responseCode,"POST request failed ${errorMsg}")
                return null
            }
        }catch (e:Exception){
//            e.printStackTrace()
            callback?.onError(NET_ERROR_CODE,"POST request failed ${e.message}")
            return null
        }

    }


    inline fun <reified T> postAsync(url:String,reqHeaders:Map<String,*>? = null,req:Any?,callBack: Net.CallBack<T>?){
        executorService.submit {
            post(url,reqHeaders, req, object :Net.CallBack<T>{
                override fun onSuccess(result: T) {
                    runOnMainThread {
                        callBack?.onSuccess(result)
                    }
                }

                override fun onError(code: Int, error: String?) {
                    runOnMainThread {
                        callBack?.onError(code,error)
                    }
                }

            })
        }
    }

    inline fun <reified T> getAsync(url:String,reqHeaders:Map<String,*>? = null,req:Map<String,*>?,callBack: Net.CallBack<T>?){
        executorService.submit {
            get(url,reqHeaders, req, object :Net.CallBack<T>{
                override fun onSuccess(result: T) {
                    runOnMainThread {
                        callBack?.onSuccess(result)
                    }
                }

                override fun onError(code: Int, error: String?) {
                    runOnMainThread {
                        callBack?.onError(code,error)
                    }
                }

            })
        }
    }






}